home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / gkismet / GKismetApplication.pm < prev    next >
Text File  |  2005-10-20  |  18KB  |  648 lines

  1. #!/usr/bin/perl -w
  2. #
  3. # $Id: GKismetApplication.pm,v 1.70 2003/08/01 01:37:00 solovam Exp $
  4. #
  5. # This file is a part of gkismet
  6. #
  7. # This program is free software; you can redistribute it and/or
  8. # modify it under the terms of the GNU General Public License
  9. # as published by the Free Software Foundation; either version 2
  10. # of the License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20. #
  21.  
  22. #
  23. # GKismetApplication class:
  24. #
  25. package GKismetApplication;
  26.  
  27. use Gnome;
  28. use PacketBox;
  29. use NetworkTree;
  30. use StatusBar;
  31. use Connection;
  32. use ConnectionDialog;
  33. use PrefsDialog;
  34. use AboutDialog;
  35. use Preferences;
  36. use PacketWindow;
  37. use StringWindow;
  38. use PowerBox;
  39. use GpsBox;
  40. use Locator;
  41. use RateGraph;
  42. use BoomBox;
  43. use Misc;
  44. use strict;
  45.  
  46. #
  47. # Constructor
  48. #
  49. sub new
  50. {
  51.     my $type = shift;
  52.     my $self = {};
  53.     bless $self, $type;
  54.  
  55.     # Paths
  56.     my $prefix = shift;
  57.     $self->{'path'}{'xpm'} = $prefix . '/share/gkismet/xpm';
  58.     $self->{'path'}{'sound'} = $prefix . '/share/gkismet/sound';
  59.     $self->{'path'}{'etc'} = '/etc/gkismet';
  60.  
  61.     # Gnome init
  62.     init Gnome 'gkismet';
  63.  
  64.     # Create app
  65.     my $application = new Gnome::App("gkismet", "gkismet");
  66.     $self->{'application'} = $application;
  67.     $application->set_default_size(Gtk::Gdk->screen_width() * 0.6, Gtk::Gdk->screen_height() * 0.8);
  68.     $application->signal_connect("delete_event", sub {Gtk->exit(0)});
  69.  
  70.     # Preferences
  71.     my $preferences = new Preferences($self);
  72.     $self->{'preferences'} = $preferences;
  73.     
  74.     # Status line
  75.     my $statusBar = new StatusBar($self);
  76.     $self->{'persistentObservers'}{'statusBar'} = $statusBar;
  77.  
  78.     # My info box
  79.     my $packetBox = new PacketBox($self);
  80.     $self->{'persistentObservers'}{'packetBox'} = $packetBox;
  81.  
  82.     # My power box
  83.     my $powerBox = new PowerBox($self);
  84.     $self->{'persistentObservers'}{'powerBox'} = $powerBox;
  85.  
  86.     # My GPS box
  87.     my $gpsBox = new GpsBox($self);
  88.     $self->{'persistentObservers'}{'gpsBox'} = $gpsBox;
  89.  
  90.     # Ntree
  91.     my $networkTree = new NetworkTree($self);
  92.     $self->{'persistentObservers'}{'networkTree'} = $networkTree;
  93.     $networkTree->addObserver($self);
  94.  
  95.     my $boomBox = new BoomBox($self);
  96.     $self->{'persistentObservers'}{'boomBox'} = $boomBox;
  97.  
  98.     # Build menu info
  99.     my @menuInfo =
  100.     (
  101.     {
  102.         type => 'subtree', label => '_File', subtree =>
  103.         [
  104.             {type => 'item', label => '_Connect', pixmap_type => 'stock', pixmap_info => 'Menu_Open',
  105.                 callback => sub {$self->connect()}},
  106.             {type => 'item', label => '_Disconnect', pixmap_type => 'stock', pixmap_info => 'Menu_Close',
  107.                 callback => sub {$self->disconnect()}},
  108.             {type => 'separator'},
  109.             {type => 'item', label => '_Quit', pixmap_type => 'stock', pixmap_info => 'Menu_Quit',
  110.                 callback => sub {Gtk->exit(0)}}
  111.         ]
  112.     },
  113.     {
  114.         type => 'subtree', label => '_View', subtree =>
  115.         [
  116.             {type => 'item', label => '_Expand', pixmap_type => 'stock', pixmap_info => 'Menu_Book Open',
  117.                 callback => sub {$self->{'persistentObservers'}{'networkTree'}->expand()}},
  118.             {type => 'item', label => '_Collapse', pixmap_type => 'stock', pixmap_info => 'Menu_Book Red',
  119.                 callback => sub {$self->{'persistentObservers'}{'networkTree'}->collapse()}},
  120.             {type => 'item', label => '_Packet Dump', pixmap_type => 'stock', pixmap_info => 'Menu_Timer',
  121.                 callback => sub {$self->bssObserverOpenSelected('PacketWindow')}},
  122.             {type => 'item', label => '_String Dump', pixmap_type => 'stock', pixmap_info => 'Menu_Timer',
  123.                 callback => sub {$self->bssObserverOpenSelected('StringWindow')}},
  124.             {type => 'item', label => '_Locate', pixmap_type => 'stock', pixmap_info => 'Menu_Search',
  125.                 callback => sub {$self->bssObserverOpenSelected('Locator')}},
  126.             {type => 'item', label => 'Packet _rate', pixmap_type => 'stock', pixmap_info => 'Menu_Timer',
  127.                 callback => sub {$self->transObserverOpen('RateGraph')}},
  128.             {type => 'subtree', label => 'Sort', subtree =>
  129.                 [
  130.                     {type => 'item', label => 'Ascending',
  131.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setSortOrder('ascending')}},
  132.                     {type => 'item', label => 'Descending',
  133.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setSortOrder('descending')}},
  134.                 ]
  135.             },
  136.             {type => 'subtree', label => 'Sort Networks', subtree =>
  137.                 [
  138.                     {type => 'item', label => 'By channel',
  139.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('channel')}},
  140.                     {type => 'item', label => 'By first seen',
  141.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('firsttime')}},
  142.                     {type => 'item', label => 'By last seen',
  143.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('lasttime')}},
  144.                     {type => 'item', label => 'By BSSID',
  145.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('bssid')}},
  146.                     {type => 'item', label => 'By SSID',
  147.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('ssid')}},
  148.                     {type => 'item', label => 'By data packet count',
  149.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('datapackets')}},
  150.                     {type => 'item', label => 'By signal power',
  151.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('signal')}},
  152.                     {type => 'item', label => 'By WEP',
  153.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setNetworksSortBy('wep')}},
  154.                 ]
  155.             },
  156.             {type => 'subtree', label => 'Sort Clients', subtree =>
  157.                 [
  158.                     {type => 'item', label => 'By first seen',
  159.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('firsttime')}},
  160.                     {type => 'item', label => 'By last seen',
  161.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('lasttime')}},
  162.                     {type => 'item', label => 'By MAC',
  163.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('mac')}},
  164.                     {type => 'item', label => 'By data packet count',
  165.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('datapackets')}},
  166.                     {type => 'item', label => 'By signal power',
  167.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('signal')}},
  168.                     {type => 'item', label => 'By WEP',
  169.                         callback => sub {$self->{'persistentObservers'}{'networkTree'}->setClientsSortBy('wep')}},
  170.                 ]
  171.             }
  172.         ]
  173.     },
  174.     {
  175.         type => 'subtree', label => '_Settings', subtree =>
  176.         [
  177.             {type => 'item', label => '_Preferences', pixmap_type => 'stock', pixmap_info => 'Menu_Preferences',
  178.                 callback => sub{$self->dialogOpen('PrefsDialog')}}
  179.         ]
  180.     },
  181.     {
  182.         type => 'subtree', label => '_Help', subtree =>
  183.         [
  184.             {type => 'item', label => '_About', pixmap_type => 'stock', pixmap_info => 'Menu_About',
  185.                 callback => sub{$self->dialogOpen('AboutDialog')}}
  186.         ]
  187.     }
  188.     );
  189.  
  190.     # Build toolbar info
  191.     my @toolbarInfo = (
  192.         {type => 'item', label => 'Connect', pixmap_type => 'stock', pixmap_info => 'Open', 'hint' => 'Connect to Kismet server',
  193.             callback => sub {$self->connect()}},
  194.         {type => 'item', label => 'Disconnect', pixmap_type => 'stock', pixmap_info => 'Close', 'hint' => 'Disconnect from Kismet server',
  195.             callback => sub {$self->disconnect()}},
  196.         {type => 'item', label => 'Expand', pixmap_type => 'stock', pixmap_info => 'Book Open', 'hint' => 'Expand network node',
  197.             callback => sub {$self->{'persistentObservers'}{'networkTree'}->expand()}},
  198.         {type => 'item', label => 'Collapse', pixmap_type => 'stock', pixmap_info => 'Book Red', 'hint' => 'Collapse network node',
  199.             callback => sub {$self->{'persistentObservers'}{'networkTree'}->collapse()}},
  200.         {type => 'item', label => 'Packet Dump', pixmap_type => 'stock', pixmap_info => 'Timer', 'hint' => 'Open packet dump window',
  201.             callback => sub {$self->bssObserverOpenSelected('PacketWindow')}},
  202.         {type => 'item', label => 'String Dump', pixmap_type => 'stock', pixmap_info => 'Timer', 'hint' => 'Open string dump window',
  203.             callback => sub {$self->bssObserverOpenSelected('StringWindow')}},
  204.         {type => 'item', label => 'Locate', pixmap_type => 'stock', pixmap_info => 'Search', 'hint' => 'Open locator window',
  205.             callback => sub {$self->bssObserverOpenSelected('Locator')}},
  206.         {type => 'item', label => 'Packet rate', pixmap_type => 'stock', pixmap_info => 'Timer', 'hint' => 'Open packet rate window',
  207.             callback => sub {$self->transObserverOpen('RateGraph')}},
  208.     );
  209.  
  210.     # Pack widgets
  211.     my $scrolledWindow = new Gtk::ScrolledWindow(undef, undef);
  212.     $scrolledWindow->set_policy('automatic', 'automatic');
  213.     my $vbox = new Gtk::VBox($false, 0);
  214.     $vbox->pack_start($packetBox->getWidget(), $false, $false, 10);
  215.     $vbox->pack_start($gpsBox->getWidget(), $false, $false, 10);
  216.     $vbox->pack_start($powerBox->getWidget(), $true, $true, 10);
  217.     my $hbox = new Gtk::HBox($false, 0);
  218.     $hbox->pack_start($scrolledWindow, $true, $true, 0);
  219.     $hbox->pack_end($vbox, $false, $false, 10);
  220.     $scrolledWindow->add($networkTree->getWidget());
  221.  
  222.     # Assemble main window
  223.     $application->create_menus(@menuInfo);
  224.     $application->create_toolbar(@toolbarInfo);
  225.     $application->set_statusbar($statusBar->getWidget());
  226.     $application->set_contents($hbox);
  227.     $application->show_all();
  228.  
  229.     # Items become active when a network is selected
  230.     $self->{'selectedActItems'}{'expandMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_Expand'); 
  231.     $self->{'selectedActItems'}{'collapseMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_Collapse');
  232.     $self->{'selectedActItems'}{'packetDumpMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_Packet Dump');
  233.     $self->{'selectedActItems'}{'stringDumpMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_String Dump');
  234.     $self->{'selectedActItems'}{'locatorMenuItem'} = $self->findWidgetInMenu(\@menuInfo, '_Locate');
  235.     $self->{'selectedActItems'}{'expandToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Expand');
  236.     $self->{'selectedActItems'}{'collapseToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Collapse');
  237.     $self->{'selectedActItems'}{'packetDumpToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Packet Dump');
  238.     $self->{'selectedActItems'}{'stringDumpToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'String Dump');
  239.     $self->{'selectedActItems'}{'locatorToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Locate');
  240.     for my $item (values %{$self->{'selectedActItems'}})
  241.     {
  242.         $item->set_sensitive($false);
  243.     }
  244.  
  245.     # Items become active when a connection is established
  246.     $self->{'connectedActItems'}{'rateMenuItem'} = $self->findWidgetInMenu(\@menuInfo, 'Packet _rate');
  247.     $self->{'connectedActItems'}{'rateToolbarItem'} = $self->findWidgetInMenu(\@toolbarInfo, 'Packet rate');
  248.     for my $item (values %{$self->{'connectedActItems'}})
  249.     {
  250.         $item->set_sensitive($false);
  251.     }
  252.  
  253.     return $self;
  254. }
  255.  
  256. #
  257. # Find widget with specific label
  258. #
  259. sub findWidgetInMenu
  260. {
  261.     my $self = shift;
  262.     my $menu = shift;
  263.     my $label = shift;
  264.  
  265.     for my $item (@{$menu})
  266.     {
  267.         my $widget = $self->findWidget($item, $label);
  268.         if(defined $widget)
  269.         {
  270.             return $widget;
  271.         }
  272.     }
  273.     return undef;
  274. }
  275.  
  276. #
  277. # Find widget for a menu/toolbar item. Plucked from Gnome-Perl samples
  278. #
  279. sub findWidget
  280. {
  281.     my $self = shift;
  282.     my $item = shift;
  283.     my $label = shift;
  284.     my $subtree;
  285.  
  286.     # Array
  287.     if(ref($item) eq 'ARRAY')
  288.     {
  289.         # If found, return
  290.         if($item->[0] eq 'item' && $item->[1] eq $label)
  291.         {
  292.             return $item->[-1];
  293.         }
  294.  
  295.         # Is there a subtree?
  296.         if($item->[0] eq 'subtree')
  297.         {
  298.             $subtree = $item->[3];
  299.         }
  300.     }
  301.     # Hash
  302.     else
  303.     {
  304.         # If found, return
  305.         if($item->{'type'} eq 'item' && $item->{'label'} eq $label)
  306.         {
  307.             return $item->{'widget'};
  308.         }
  309.  
  310.         # Is there a subtree?
  311.         if ($item->{type} eq 'radioitems')
  312.         {
  313.                         $subtree = $item->{'moreinfo'};
  314.                 }
  315.         if($item->{'type'} eq 'subtree')
  316.         {
  317.             $subtree = $item->{'subtree'};
  318.         }
  319.     }
  320.  
  321.     # If there was a subtree
  322.     if(defined $subtree)
  323.     {
  324.         for (@{$subtree})
  325.         {
  326.             my $widget = $self->findWidget($_, $label);
  327.             if(defined $widget)
  328.             {
  329.                 return $widget;
  330.             }
  331.         }
  332.         }
  333.  
  334.     # Not found
  335.     return undef;
  336. }
  337.  
  338. #
  339. # Connect to server
  340. #
  341. sub connect
  342. {
  343.     my $self = shift;
  344.     my $host = shift;
  345.     my $port = shift;
  346.  
  347.     if(defined $self->{'connection'})
  348.     {
  349.         $self->disconnect();
  350.     }
  351.  
  352.     if(!defined $host || !defined $port)
  353.     {
  354.         my $connectionDialog = new ConnectionDialog($self);
  355.         ($host, $port) = $connectionDialog->runAndClose();
  356.         if(!defined $host)
  357.         {
  358.             return(0);
  359.         }
  360.     }
  361.  
  362.     my $connection = new Connection($self, $host, $port);
  363.     if(!defined $connection)
  364.     {
  365.         my $messagebox = new Gnome::MessageBox("Can't connect to kismet server at $host:$port", 'error', 'Button_Ok');
  366.         $messagebox->run_and_close();
  367.         return(0);
  368.     }
  369.     $self->{'connection'} = $connection;
  370.  
  371.     $connection->addObserver($self);
  372.  
  373.     for my $item (values %{$self->{'connectedActItems'}})
  374.     {
  375.         $item->set_sensitive($true);
  376.     }
  377.  
  378.     for my $observer (values %{$self->{'persistentObservers'}})
  379.     {
  380.         $observer->startObserving($connection);
  381.     }
  382.  
  383.     return(1);
  384. }
  385.  
  386. #
  387. # Disconnect
  388. #
  389. sub disconnect
  390. {
  391.     my $self = shift;
  392.  
  393.     if(!defined $self->{'connection'})
  394.     {
  395.         return;
  396.     }
  397.  
  398.     for my $observer (values %{$self->{'persistentObservers'}})
  399.     {
  400.         $observer->stopObserving();
  401.     }
  402.     for my $type (keys %{$self->{'transientObservers'}})
  403.     {
  404.         $self->transObserverClose($type);
  405.     }
  406.     for my $type (keys %{$self->{'bssObservers'}})
  407.     {
  408.         for my $bssid (keys %{$self->{'bssObservers'}{$type}})
  409.         {
  410.             $self->bssObserverClose($type, $bssid);
  411.         }
  412.     }
  413.  
  414.     for my $item (values %{$self->{'connectedActItems'}})
  415.     {
  416.         $item->set_sensitive($false);
  417.     }
  418.  
  419.     $self->{'connection'}->removeObserver($self);
  420.  
  421.     $self->{'connection'}->disconnect();
  422.  
  423.     delete $self->{'connection'};
  424. }
  425.  
  426. #
  427. # Handle server quit
  428. #
  429. sub update
  430. {
  431.     my $self = shift;
  432.     my $object = shift;
  433.     my $data = shift;
  434.  
  435.     if($object->isa('Connection') && defined $self->{'connection'} && $self->{'connection'} eq $object)
  436.     {
  437.         if($data->{'changed'} eq 'disconnected')
  438.         {
  439.             my $messagebox = new Gnome::MessageBox("Lost connection to kismet server at " .
  440.                 $self->{'connection'}->host() . ":" . $self->{'connection'}->port(), 'error', 'Button_Ok');
  441.             $messagebox->run_and_close();
  442.  
  443.             $self->disconnect();
  444.         }
  445.     }
  446.     elsif($object->isa('NetworkTree') && $self->{'persistentObservers'}{'networkTree'} eq $object)
  447.     {
  448.         if($data->{'changed'} eq 'selection')
  449.         {
  450.             if($self->{'persistentObservers'}{'networkTree'}->getSelectedNetworks())
  451.             {
  452.                 for my $item (values %{$self->{'selectedActItems'}})
  453.                 {
  454.                     $item->set_sensitive($true);
  455.                 }
  456.             }
  457.             else
  458.             {
  459.                 for my $item (values %{$self->{'selectedActItems'}})
  460.                 {
  461.                     $item->set_sensitive($false);
  462.                 }
  463.             }
  464.         }
  465.     }
  466. }
  467.  
  468. #
  469. # Run the app
  470. #
  471. sub run
  472. {
  473.     my $self = shift;
  474.  
  475.     my ($progname) = ($0 =~ /([^\/]*)$/);
  476.     my $usage = "$progname <host> [port]\n";
  477.  
  478.     if($#ARGV > 1)
  479.     {
  480.         print $usage;
  481.         exit 1;
  482.     }
  483.  
  484.     my $host = $ARGV[0];
  485.     my $port = $ARGV[1] ? $ARGV[1] : 2501;
  486.  
  487.     $self->connect($host, $port);
  488.  
  489.     main Gtk;
  490.  
  491.     exit(0);
  492. }
  493.  
  494. #
  495. # Get widget
  496. #
  497. sub getWidget
  498. {
  499.     my $self = shift;
  500.     return $self->{'application'};
  501. }
  502.  
  503. #
  504. # Show a dialog
  505. #
  506. sub dialogOpen
  507. {
  508.     my $self = shift;
  509.     my $type = shift;
  510.     $type = lcfirst($type);
  511.     if(!defined $self->{'dialogs'}{$type})
  512.     {
  513.         my $dialog = ucfirst($type)->new($self);
  514.         $self->{'dialogs'}{$type} = $dialog;
  515.     }
  516.     else
  517.     {
  518.         $self->{'dialogs'}{$type}->getWidget()->window()->raise();
  519.     }
  520. }
  521.  
  522. #
  523. # Close dialog
  524. #
  525. sub dialogClose
  526. {
  527.     my $self = shift;
  528.     my $type = shift;
  529.     $type = lcfirst($type);
  530.     delete $self->{'dialogs'}{$type};
  531. }
  532.  
  533. #
  534. # Return number of observers by type
  535. #
  536. sub countObservers
  537. {
  538.     my $self = shift;
  539.     my $type = shift;
  540.     $type = lcfirst($type);
  541.     return scalar keys %{$self->{'bssObservers'}{$type}};
  542. }
  543.  
  544. #
  545. # Open observers for selected networks
  546. #
  547. sub bssObserverOpenSelected
  548. {
  549.     my $self = shift;
  550.     my $type = shift;
  551.     my @selected = $self->{'persistentObservers'}{'networkTree'}->getSelectedNetworks();
  552.     for my $bssid (@selected)
  553.     {
  554.         $self->bssObserverOpen($type, $bssid);
  555.     }
  556. }
  557.  
  558. #
  559. # Open an observer for bssid
  560. #
  561. sub bssObserverOpen
  562. {
  563.     my $self = shift;
  564.     my $type = shift;
  565.     my $bssid = shift;
  566.  
  567.     $type = lcfirst($type);
  568.     if(!defined $self->{'bssObservers'}{$type}{$bssid})
  569.     {
  570.         $self->{'bssObservers'}{$type}{$bssid} = ucfirst($type)->new($self, $self->{'connection'}, $bssid);
  571.     }
  572.     else
  573.     {
  574.         $self->{'bssObservers'}{$type}{$bssid}->getWidget()->window()->raise();
  575.     }
  576. }
  577.  
  578. #
  579. # Close observers for selected networks
  580. #
  581. sub bssObserverCloseSelected
  582. {
  583.     my $self = shift;
  584.     my $type = shift;
  585.     my @selected = $self->{'persistentObservers'}{'networkTree'}->getSelectedNetworks();
  586.     for my $bssid (@selected)
  587.     {
  588.         $self->bssObserverClose($type, $bssid);
  589.     }
  590. }
  591.  
  592. #
  593. # Close an observer for bssid
  594. #
  595. sub bssObserverClose
  596. {
  597.     my $self = shift;
  598.     my $type = shift;
  599.     my $bssid = shift;
  600.     $type = lcfirst($type);
  601.     if(defined $self->{'bssObservers'}{$type}{$bssid})
  602.     {
  603.         $self->{'bssObservers'}{$type}{$bssid}->close();
  604.         delete $self->{'bssObservers'}{$type}{$bssid};
  605.     }
  606. }
  607.  
  608. #
  609. # Open observer
  610. #
  611. sub transObserverOpen
  612. {    
  613.     my $self = shift;
  614.     my $type = shift;
  615.  
  616.     if(!defined $self->{'connection'})
  617.     {
  618.         return;
  619.     }
  620.  
  621.     $type = lcfirst($type);
  622.     if(!defined $self->{'transientObservers'}{$type})
  623.     {
  624.         $self->{'transientObservers'}{$type} = ucfirst($type)->new($self, $self->{'connection'});
  625.     }
  626.     else
  627.     {
  628.         $self->{'transientObservers'}{$type}->getWidget()->window()->raise();
  629.     }
  630. }
  631.  
  632. #
  633. # Close observer
  634. #
  635. sub transObserverClose
  636. {
  637.     my $self = shift;
  638.     my $type = shift;
  639.     $type = lcfirst($type);
  640.     if(defined $self->{'transientObservers'}{$type})
  641.     {
  642.         $self->{'transientObservers'}{$type}->close();
  643.         delete $self->{'transientObservers'}{$type};
  644.     }
  645. }
  646.  
  647. 1;
  648.